﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using PCDoctor.Utils;
using System.IO;
using System.Diagnostics;

namespace PCDoctor.ScanParameters
{
    public class FileSystemScanParameter : ScanParameter
    {
        public FileSystemScanParameter(string name, string path, string value, Int64 problemId) :
            base(name, path, value, problemId)
        {
            Kind = ScanFixerKinds.FileSystem;
        }

        protected int ScanRecycleBin()
        {
            int result = 0;
            string[] DriveList = Environment.GetLogicalDrives();
            foreach (string driveLetter in DriveList)
            {
                DriveInfo di = new DriveInfo(driveLetter);
                if (di.DriveType == DriveType.Fixed)
                {
                    result += FilesCount(Path.Combine(driveLetter, "$RECYCLE.BIN"));
                }
            }
            result -= DriveList.Length;
            return result;
        }

        protected int EmptyRecycleBin()
        {
            int result = 0;
            string[] DriveList = Environment.GetLogicalDrives();
            foreach (string driveLetter in DriveList)
            {
                DriveInfo di = new DriveInfo(driveLetter);
                if (di.DriveType == DriveType.Fixed)
                {
                    result += RemoveFiles(Path.Combine(driveLetter, "$RECYCLE.BIN"));
                }
            }
            return result;
        }

        protected int RemoveRecycleFiles(string path)
        {
            int result = 0;
            string[] DriveList = Environment.GetLogicalDrives();
            foreach (string driveLetter in DriveList)
            {
                DriveInfo di = new DriveInfo(driveLetter);
                if (di.DriveType == DriveType.Fixed)
                {
                    result += RemoveFiles(Path.Combine(driveLetter, "$RECYCLE.BIN"));
                }
            }
            return result;
        }

        protected int RemoveFiles(string path)
        {
            int result = 0;
            try
            {
                DirectoryInfo di = new DirectoryInfo(path);
                DirectoryInfo[] dirs = di.GetDirectories();
                foreach (DirectoryInfo d in dirs)
                {
          //          startDeletingProcess(d.FullName);
                    FileInfo[] fi = d.GetFiles();
                    foreach (FileInfo f in fi)
                    {
                        try
                        {
                            File.Delete(f.FullName);
                            result++;
                        }
                        catch (Exception e)
                        {
                            ErrorHandler.HandleError(e.Message);
                        }
                    }
                    result += RemoveFiles(d.FullName);
                }
                try
                {
                    Directory.Delete(path, true);
                }
                catch (Exception e)
                {
                    ErrorHandler.HandleError(e.Message);
                }
            }
            catch (Exception e)
            {
                ErrorHandler.HandleError(e.Message);
            }
            return result;
        }

        protected int FilesCount(string path)
        {
            int result = 0;
            try
            {
                DirectoryInfo di = new DirectoryInfo(path);
                result += di.GetFiles().Length;
                DirectoryInfo[] dirs = di.GetDirectories();
                foreach (DirectoryInfo d in dirs)
                {
                    result += FilesCount(d.FullName);
                }
            }
            catch (Exception e)
            {
                ErrorHandler.HandleError(e.Message);
            }
            return result;
        }

        public override FixationResult Fix()
        {
            if (this.Result == ScanResult.OK)
            {
                FixResult = FixationResult.NoNeedToFix;
                return FixationResult.NoNeedToFix;
            }
            FixedProblems = 0;
            foreach (KeyValuePair<string, string> pv in PathsValues)
            {
                string[] parts = pv.Key.Split(':');
                string path = "";
                switch (parts[0]) //получаем место сканирования
                {
                    case "EnvironmentMachine":
                        path = Environment.GetEnvironmentVariable("temp", EnvironmentVariableTarget.Machine);
                        break;
                    case "EnvironmentUser":
                        path = Environment.GetEnvironmentVariable("temp", EnvironmentVariableTarget.User);
                        break;
                    case "Registry":
                        try
                        {
                            string[] regParts = parts[1].Split('\\');
                            string resultKey = "";
                            for (int i = 0; i < regParts.Length - 1; i++)
                            {
                                resultKey += regParts[i];
                                if (i < regParts.Length - 2)
                                {
                                    resultKey += "\\";
                                }
                            }
                            RegistryKey rk = Registry.CurrentUser.OpenSubKey(resultKey);
                            path = rk.GetValue(regParts[regParts.Length - 1]).ToString();
                        }
                        catch (Exception e)
                        {
                            path = "";
                            ErrorHandler.HandleError(e.Message);
                        }
                        break;
                    case "Drives":
                        path = "recycle";
                        break;
                }
                if (path != "")
                {
                    if (path == "recycle")
                    {
                        FixedProblems += RemoveRecycleFiles(path);
                        //ProblemsCount += ScanRecycleBin(); //Сканируем корзину
                    }
                    else
                    {
                        FixedProblems += RemoveFiles(path); //Сканируем папку
                    }
                }
            }
            return FixationResult.Fixed;
        }

        public override bool Scan()
        {
            foreach (KeyValuePair<string, string> pv in PathsValues)
            {
                string[] parts = pv.Key.Split(':');
                string path = "";
                switch (parts[0]) //получаем место сканирования
                {
                    case "EnvironmentMachine":
                        path = Environment.GetEnvironmentVariable("temp", EnvironmentVariableTarget.Machine);
                        break;
                    case "EnvironmentUser":
                        path = Environment.GetEnvironmentVariable("temp", EnvironmentVariableTarget.User);
                        break;
                    case "Registry":
                        try
                        {
                            string[] regParts = parts[1].Split('\\');
                            string resultKey = "";
                            for (int i = 0; i < regParts.Length - 1; i++)
                            {
                                resultKey += regParts[i];
                                if (i < regParts.Length - 2)
                                {
                                    resultKey += "\\";
                                }
                            }
                            RegistryKey rk = Registry.CurrentUser.OpenSubKey(resultKey);
                            path = rk.GetValue(regParts[regParts.Length - 1]).ToString();
                        }
                        catch (Exception e)
                        {
                            path = "";
                            ErrorHandler.HandleError(e.Message);
                        }
                        break;
                    case "Drives":
                        path = "recycle";
                        break;
                }
                if (path != "")
                {
                    if (path == "recycle")
                    {
                        ProblemsCount += ScanRecycleBin(); //Сканируем корзину
                    }
                    else
                    {
                        ProblemsCount += FilesCount(path); //Сканируем папку
                    }
                    if (ProblemsCount > 0)
                    {
                        Result = ScanResult.SemiProblem;
                    }
                }
            }
            if (Result == ScanResult.NotScanned)
            {
                Result = ScanResult.OK;
            }
            return true;
        }

    }
}